//====================================================================================================
// [插件名称] jQuery formValidator
//----------------------------------------------------------------------------------------------------
// [描    述] jQuery formValidator表单验证插件，它是基于jQuery类库，实现了js脚本于页面的分离。对一个表
//            单对象，你只需要写一行代码就可以轻松实现20种以上的脚本控制。现支持一个表单元素累加很多种
//            校验方式,采用配置信息的思想，而不是把信息写在表单元素上，能比较完美的实现ajax请求。
//----------------------------------------------------------------------------------------------------
// [作者网名] 猫冬	
// [邮    箱] wzmaodong@126.com
// [作者博客] http://wzmaodong.cnblogs.com
// [更新日期] 2008-01-24
// [版 本 号] ver3.3
//====================================================================================================
var jQuery_formValidator_initConfig;
(function($) {

	$.formValidator = {
		// 各种校验方式支持的控件类型
		sustainType : function(id, setting) {
			var elem = $("#" + id).get(0);
			var srcTag = elem.tagName;
			var stype = elem.type;
			switch (setting.validatetype) {
			case "InitValidator":
				return true;
			case "InputValidator":
				if (srcTag == "INPUT" || srcTag == "TEXTAREA"
						|| srcTag == "SELECT") {
					return true;
				} else {
					return false;
				}
			case "CompareValidator":
				if (srcTag == "INPUT" || srcTag == "TEXTAREA") {
					if (stype == "checkbox" || stype == "radio") {
						return false;
					} else {
						return true;
					}
				}
				return false;
			case "AjaxValidator":
				if (stype == "text" || stype == "textarea" || stype == "file"
						|| stype == "password" || stype == "select-one") {
					return true;
				} else {
					return false;
				}
			case "RegexValidator":
				if (srcTag == "INPUT" || srcTag == "TEXTAREA") {
					if (stype == "checkbox" || stype == "radio") {
						return false;
					} else {
						return true;
					}
				}
				return false;
			case "FunctionValidator":
				return true;
			}
		},

		initConfig : function(controlOptions) {
			var settings = {
				debug : false,
				validatorgroup : "1",
				alertmessage : false,
				validobjectids : "",
				forcevalid : false,
				onsuccess : function() {
					return true;
				},
				onerror : function() {
				},
				submitonce : false,
				formid : "",
				autotip : false,
				tidymode : false,
				errorfocus : true,
				wideword : true
			};
			controlOptions = controlOptions || {};
			$.extend(settings, controlOptions);
			// 如果是精简模式，发生错误的时候，第一个错误的控件就不获得焦点
			if (settings.tidymode) {
				settings.errorfocus = false
			}
			;
			if (settings.formid != "") {
				$("#" + settings.formid).submit(function() {
					return $.formValidator.pageIsValid("1");
				})
			}
			;
			if (jQuery_formValidator_initConfig == null) {
				jQuery_formValidator_initConfig = new Array();
			}
			jQuery_formValidator_initConfig.push(settings);
		},

		// 如果validator对象对应的element对象的validator属性追加要进行的校验。
		appendValid : function(id, setting) {
			// 如果是各种校验不支持的类型，就不追加到。返回-1表示没有追加成功
			if (!$.formValidator.sustainType(id, setting))
				return -1;
			var srcjo = $("#" + id).get(0);
			// 重新初始化
			if (setting.validatetype == "InitValidator"
					|| srcjo.settings == undefined) {
				srcjo.settings = new Array();
			}
			var len = srcjo.settings.push(setting);
			srcjo.settings[len - 1].index = len - 1;
			return len - 1;
		},

		// 如果validator对象对应的element对象的validator属性追加要进行的校验。
		getInitConfig : function(validatorgroup) {
			if (jQuery_formValidator_initConfig != null) {
				for (i = 0; i < jQuery_formValidator_initConfig.length; i++) {
					if (validatorgroup == jQuery_formValidator_initConfig[i].validatorgroup) {
						return jQuery_formValidator_initConfig[i];
					}
				}
			}
			return null;
		},

		// 触发每个控件上的各种校验
		triggerValidate : function(returnObj) {
			switch (returnObj.setting.validatetype) {
			case "InputValidator":
				$.formValidator.inputValid(returnObj);
				break;
			case "CompareValidator":
				$.formValidator.compareValid(returnObj);
				break;
			case "AjaxValidator":
				$.formValidator.ajaxValid(returnObj);
				break;
			case "RegexValidator":
				$.formValidator.regexValid(returnObj);
				break;
			case "FunctionValidator":
				$.formValidator.functionValid(returnObj);
				break;
			}
		},

		// 设置显示信息
		setTipState : function(elem, showclass, showmsg) {
			var setting0 = elem.settings[0];
			var initConfig = $.formValidator
					.getInitConfig(setting0.validatorgroup);
			var tip = $("#" + setting0.tipid);
			if (showmsg == null || showmsg == "") {
				tip.hide();
			} else {
				if (initConfig.tidymode) {
					// 显示和保存提示信息
					$("#fv_content").html(showmsg);
					elem.Tooltip = showmsg;
					if (showclass != "onError") {
						tip.hide();
					}
				}
				tip.removeClass();
				tip.addClass(showclass);
				tip.html(showmsg);
			}
		},

		resetTipState : function(validatorgroup) {
			var initConfig = $.formValidator.getInitConfig(validatorgroup);
			$(initConfig.validobjectids).each(
					function() {
						$.formValidator.setTipState(this, "onShow",
								this.settings[0].onshow);
					});
		},

		// 设置错误的显示信息
		setFailState : function(tipid, showmsg) {
			var tip = $("#" + tipid);
			tip.removeClass();
			tip.addClass("onError");
			tip.html(showmsg);
		},

		// 根据单个对象,正确:正确提示,错误:错误提示
		showMessage : function(returnObj) {
			var id = returnObj.id;
			var elem = $("#" + id).get(0);
			var isvalid = returnObj.isvalid;
			var setting = returnObj.setting;// 正确:setting[0],错误:对应的setting[i]
			var showmsg = "", showclass = "";
			var settings = $("#" + id).get(0).settings;
			var intiConfig = $.formValidator
					.getInitConfig(settings[0].validatorgroup);
			if (!isvalid) {
				showclass = "onError";
				if (setting.validatetype == "AjaxValidator") {
					if (setting.lastValid == "") {
						showclass = "onLoad";
						showmsg = setting.onwait;
					} else {
						showmsg = setting.onerror;
					}
				} else {
					showmsg = (returnObj.errormsg == "" ? setting.onerror
							: returnObj.errormsg);

				}
				if (intiConfig.alertmessage) {
					var elem = $("#" + id).get(0);
					if (elem.validoldvalue != $(elem).val()) {
						alert(showmsg);
					}
				} else {
					$.formValidator.setTipState(elem, showclass, showmsg);
				}
			} else {
				// 验证成功后,如果没有设置成功提示信息,则给出默认提示,否则给出自定义提示;允许为空,值为空的提示
				showmsg = $.formValidator.isEmpty(id) ? setting.onempty
						: setting.oncorrect;
				$.formValidator.setTipState(elem, "onCorrect", showmsg);
			}
			return showmsg;
		},

		showAjaxMessage : function(returnObj) {
			var setting = returnObj.setting;
			var elem = $("#" + returnObj.id).get(0);
			if (elem.validoldvalue != $(elem).val()) {
				$.formValidator.ajaxValid(returnObj);
			} else {
				if (setting.isvalid != undefined && !setting.isvalid) {
					elem.lastshowclass = "onError";
					elem.lastshowmsg = setting.onerror;
				}
				$.formValidator.setTipState(elem, elem.lastshowclass,
						elem.lastshowmsg);
			}
		},

		// 获取指定字符串的长度
		getLength : function(id) {
			var srcjo = $("#" + id);
			var elem = srcjo.get(0);
			sType = elem.type;
			var len = 0;
			switch (sType) {
			case "text":
			case "hidden":
			case "password":
			case "textarea":
			case "file":
				var val = srcjo.val();
				var initConfig = $.formValidator
						.getInitConfig(elem.settings[0].validatorgroup);
				if (initConfig.wideword) {
					for ( var i = 0; i < val.length; i++) {
						if (val.charCodeAt(i) >= 0x4e00
								&& val.charCodeAt(i) <= 0x9fa5) {
							len += 2;
						} else {
							len++;
						}
					}
				} else {
					len = val.length;
				}
				break;
			case "checkbox":
			case "radio":
				len = $("input[@type='" + sType + "'][@name='"
						+ srcjo.attr("name") + "'][@checked]").length;
				break;
			case "select-one":
				len = elem.options ? elem.options.selectedIndex : -1;
				break;
			case "select-multiple":
				len = $("select[@name=" + elem.name + "] option[@selected]").length;
				break;
			}
			return len;
		},

		// 结合empty这个属性，判断仅仅是否为空的校验情况。
		isEmpty : function(id) {
			if ($("#" + id).get(0).settings[0].empty
					&& $.formValidator.getLength(id) == 0) {
				return true;
			} else {
				return false;
			}
		},

		// 对外调用：判断单个表单元素是否验证通过，不带回调函数
		isOneValid : function(id) {
			return $.formValidator.oneIsValid(id, 1).isvalid;
		},

		// 验证单个是否验证通过,正确返回settings[0],错误返回对应的settings[i]
		oneIsValid : function(id, index) {
			var returnObj = new Object();
			returnObj.id = id;
			returnObj.ajax = -1;
			returnObj.errormsg = ""; // 自定义错误信息
			var elem = $("#" + id).get(0);
			var settings = elem.settings;
			var settingslen = settings.length;
			// 只有一个formValidator的时候不检验
			if (settingslen == 1) {
				settings[0].bind = false;
			}
			if (!settings[0].bind) {
				return null;
			}
			for ( var i = 0; i < settingslen; i++) {
				if (i == 0) {
					if ($.formValidator.isEmpty(id)) {
						returnObj.isvalid = true;
						returnObj.setting = settings[0];
						break;
					}
					continue;
				}
				returnObj.setting = settings[i];
				if (settings[i].validatetype != "AjaxValidator") {
					$.formValidator.triggerValidate(returnObj);
				} else {
					returnObj.ajax = i;
				}
				if (!settings[i].isvalid) {
					returnObj.isvalid = false;
					returnObj.setting = settings[i];
					break;
				} else {
					returnObj.isvalid = true;
					returnObj.setting = settings[0];
					if (settings[i].validatetype == "AjaxValidator")
						break;
				}
			}
			return returnObj;
		},

		// 验证所有需要验证的对象，并返回是否验证成功。
		pageIsValid : function(validatorgroup) {
			if (validatorgroup == null || validatorgroup == undefined) {
				validatorgroup = "1"
			}
			;
			var isvalid = true;
			var thefirstid = "", thefirsterrmsg;
			var returnObj, setting;
			var error_tip = "^";

			var initConfig = $.formValidator.getInitConfig(validatorgroup);
			var jqObjs = $(initConfig.validobjectids);
			jqObjs
					.each(function(i, elem) {
						if (elem.settings[0].bind) {
							returnObj = $.formValidator.oneIsValid(elem.id, 1);
							if (returnObj) {
								var tipid = elem.settings[0].tipid;
								// 校验失败,获取第一个发生错误的信息和ID
								if (!returnObj.isvalid) {
									isvalid = false;
									if (thefirstid == "") {
										thefirstid = returnObj.id;
										thefirsterrmsg = (returnObj.errormsg == "" ? returnObj.setting.onerror
												: returnObj.errormsg)
									}
								}
								// 为了解决使用同个TIP提示问题:后面的成功或失败都不覆盖前面的失败
								if (!initConfig.alertmessage) {
									if (error_tip.indexOf("^" + tipid + "^") == -1) {
										if (!returnObj.isvalid) {
											error_tip = error_tip + tipid + "^";
										}
										$.formValidator.showMessage(returnObj);
									}
								}
							}
						}
					});
			// 成功或失败后，进行回调函数的处理，以及成功后的灰掉提交按钮的功能
			if (isvalid) {
				isvalid = initConfig.onsuccess();
				if (initConfig.submitonce) {
					$("input[@type='submit']").attr("disabled", true);
				}
			} else {
				var obj = $("#" + thefirstid).get(0);
				initConfig.onerror(thefirsterrmsg, obj);
				if (thefirstid != "" && initConfig.errorfocus) {
					$("#" + thefirstid).focus();
				}
			}
			return !initConfig.debug && isvalid;
		},

		// ajax校验
		ajaxValid : function(returnObj) {
			var id = returnObj.id;
			var srcjo = $("#" + id);
			var elem = srcjo.get(0);
			var settings = elem.settings;
			var setting = settings[returnObj.ajax];
			var ls_url = setting.url;
			if (srcjo.size() == 0 && settings[0].empty) {
				returnObj.setting = settings[0];
				returnObj.isvalid = true;
				$.formValidator.showMessage(returnObj);
				setting.isvalid = true;
				return;
			}
			if (setting.addidvalue) {
				var parm = "clientid=" + id + "&" + id + "="
						+ encodeURIComponent(srcjo.val());
				ls_url = ls_url
						+ (ls_url.indexOf("?") > 0 ? ("&" + parm)
								: ("?" + parm));
			}
			$.ajax({
				mode : "abort",
				type : setting.type,
				url : ls_url,
				cache : setting.cache,
				data : setting.data,
				async : setting.async,
				dataType : setting.datatype,
				success : function(data) {
					if (setting.success(data)) {
						$.formValidator.setTipState(elem, "onCorrect",
								settings[0].oncorrect);
						setting.isvalid = true;
					} else {
						$.formValidator.setTipState(elem, "onError",
								setting.onerror);
						setting.isvalid = false;
					}
				},
				complete : function() {
					if (setting.buttons && setting.buttons.length > 0) {
						setting.buttons.attr({
							"disabled" : false
						})
					}
					;
					setting.complete;
				},
				beforeSend : function(xhr) {
					// 再服务器没有返回数据之前，先回调提交按钮
					if (setting.buttons && setting.buttons.length > 0) {
						setting.buttons.attr({
							"disabled" : true
						})
					}
					;
					var isvalid = setting.beforesend(xhr);
					if (isvalid) {
						setting.isvalid = false; // 如果前面ajax请求成功了，再次请求之前先当作错误处理
						$.formValidator.setTipState(elem, "onLoad",
								settings[returnObj.ajax].onwait);
					}
					setting.lastValid = "-1";
					return isvalid;
				},
				error : function() {
					$.formValidator.setTipState(elem, "onError",
							setting.onerror);
					setting.isvalid = false;
					setting.error();
				},
				processData : setting.processdata
			});
		},

		// 对正则表达式进行校验（目前只针对input和textarea）
		regexValid : function(returnObj) {
			var id = returnObj.id;
			var setting = returnObj.setting;
			var srcTag = $("#" + id).get(0).tagName;
			var elem = $("#" + id).get(0);
			// 如果有输入正则表达式，就进行表达式校验
			
			if (elem.settings[0].empty && elem.value == "") {
				setting.isvalid = true;
			} else {
				var regexpress = setting.regexp;
				if (setting.datatype == "enum") {
					regexpress = eval("regexEnum." + regexpress);
				}
				if (regexpress == undefined || regexpress == "") {
					setting.isvalid = false;
					return;
				}
				setting.isvalid = (new RegExp(regexpress, setting.param))
						.test($("#" + id).val());
			}
		},

		// 函数校验。返回true/false表示校验是否成功;返回字符串表示错误信息，校验失败;如果没有返回值表示处理函数，校验成功
		functionValid : function(returnObj) {
			var id = returnObj.id;
			var setting = returnObj.setting;
			var srcjo = $("#" + id);
			var lb_ret = setting.fun(srcjo.val(), srcjo.get(0));
			if (lb_ret != undefined) {
				if (typeof lb_ret == "string") {
					setting.isvalid = false;
					returnObj.errormsg = lb_ret;
				} else {
					setting.isvalid = lb_ret;
				}
			}
		},

		// 对input和select类型控件进行校验
		inputValid : function(returnObj) {
			var id = returnObj.id;
			var setting = returnObj.setting;
			var srcjo = $("#" + id);
			var elem = srcjo.get(0);
			var val = srcjo.val();
			var sType = elem.type;
			var len = $.formValidator.getLength(id);
			var empty = setting.empty, emptyerror = false;
			switch (sType) {
			case "text":
			case "hidden":
			case "password":
			case "textarea":
			case "file":
				if (setting.type == "size") {
					empty = setting.empty;
					if (!empty.leftempty) {
						emptyerror = (val.replace(/^[ \s]+/, '').length != val.length);
					}
					if (!emptyerror && !empty.rightempty) {
						emptyerror = (val.replace(/[ \s]+$/, '').length != val.length);
					}
					if (emptyerror && empty.emptyerror) {
						returnObj.errormsg = empty.emptyerror
					}
				}
			case "checkbox":
			case "select-one":
			case "select-multiple":
			case "radio":
				var lb_go_on = false;
				if (sType == "select-one" || sType == "select-multiple") {
					setting.type = "size";
				}
				var type = setting.type;
				if (type == "size") { // 获得输入的字符长度，并进行校验
					if (!emptyerror) {
						lb_go_on = true
					}
					if (lb_go_on) {
						val = len
					}
				} else if (type == "date" || type == "datetime") {
					var isok = false;
					if (type == "date") {
						lb_go_on = isDate(val)
					}
					;
					if (type == "datetime") {
						lb_go_on = isDate(val)
					}
					;
					if (lb_go_on) {
						val = new Date(val);
						setting.min = new Date(setting.min);
						setting.max = new Date(setting.max);
					}
					;
				} else {
					stype = (typeof setting.min);
					if (stype == "number") {
						val = (new Number(val)).valueOf();
						if (!isNaN(val)) {
							lb_go_on = true;
						}
					}
					if (stype == "string") {
						lb_go_on = true;
					}
				}
				setting.isvalid = false;
				if (lb_go_on) {
					if (val < setting.min || val > setting.max) {
						if (val < setting.min && setting.onerrormin) {
							returnObj.errormsg = setting.onerrormin;
						}
						if (val > setting.min && setting.onerrormax) {
							returnObj.errormsg = setting.onerrormax;
						}
					} else {
						setting.isvalid = true;
					}
				}
				break;
			}
		},

		compareValid : function(returnObj) {
			var id = returnObj.id;
			var setting = returnObj.setting;
			var srcjo = $("#" + id);
			var desjo = $("#" + setting.desid);
			var ls_datatype = setting.datatype;
			setting.isvalid = false;
			curvalue = srcjo.val();
			ls_data = desjo.val();
			if (ls_datatype == "number") {
				if (!isNaN(curvalue) && !isNaN(ls_data)) {
					curvalue = parseFloat(curvalue);
					ls_data = parseFloat(ls_data);
				} else {
					return;
				}
			}
			if (ls_datatype == "date" || ls_datatype == "datetime") {
				var isok = false;
				if (ls_datatype == "date") {
					isok = (isDate(curvalue) && isDate(ls_data))
				}
				;
				if (ls_datatype == "datetime") {
					isok = (isDateTime(curvalue) && isDateTime(ls_data))
				}
				;
				if (isok) {
					curvalue = new Date(curvalue);
					ls_data = new Date(ls_data)
				} else {
					return;
				}
			}

			switch (setting.operateor) {
			case "=":
				if (curvalue == ls_data) {
					setting.isvalid = true;
				}
				break;
			case "!=":
				if (curvalue != ls_data) {
					setting.isvalid = true;
				}
				break;
			case ">":
				if (curvalue > ls_data) {
					setting.isvalid = true;
				}
				break;
			case ">=":
				if (curvalue >= ls_data) {
					setting.isvalid = true;
				}
				break;
			case "<":
				if (curvalue < ls_data) {
					setting.isvalid = true;
				}
				break;
			case "<=":
				if (curvalue <= ls_data) {
					setting.isvalid = true;
				}
				break;
			}
		},

		localTooltip : function(e) {
			e = e || window.event;
			var mouseX = e.pageX
					|| (e.clientX ? e.clientX + document.body.scrollLeft : 0);
			var mouseY = e.pageY
					|| (e.clientY ? e.clientY + document.body.scrollTop : 0);
			$("#fvtt").css({
				"top" : (mouseY + 2) + "px",
				"left" : (mouseX - 40) + "px"
			});
		}
	};

	// 每个校验控件必须初始化的
	$.fn.formValidator = function(cs) {
		var setting = {
			validatorgroup : "1",
			empty : false,
			submitonce : false,
			automodify : false,
			onshow : "请输入内容",
			onfocus : "请输入内容",
			oncorrect : "输入正确",
			onempty : "输入内容为空",
			defaultvalue : null,
			bind : true,
			validatetype : "InitValidator",
			tipcss : {
				"left" : "10px",
				"top" : "1px",
				"height" : "20px",
				"width" : "250px"
			},
			triggerevent : "blur",
			forcevalid : false
		};

		// 获取该校验组的全局配置信息
		cs = cs || {};
		if (cs.validatorgroup == undefined) {
			cs.validatorgroup = "1"
		}
		;
		var initConfig = $.formValidator.getInitConfig(cs.validatorgroup);

		// 如果为精简模式，tipcss要重新设置初始值
		if (initConfig.tidymode) {
			setting.tipcss = {
				"left" : "2px",
				"width" : "22px",
				"height" : "22px",
				"display" : "none"
			}
		}
		;

		// 先合并整个配置(深度拷贝)
		$.extend(true, setting, cs);

		return this
				.each(function(e) {
					var jqobj = $(this);
					var setting_temp = {};
					$.extend(true, setting_temp, setting);
					var tip = setting_temp.tipid ? setting_temp.tipid : this.id
							+ "Tip";
					// 自动形成TIP
					if (initConfig.autotip) {
						// 获取层的ID、相对定位控件的ID和坐标
						if ($("body [id=" + tip + "]").length == 0) {
							aftertip = setting_temp.relativeid ? setting_temp.relativeid
									: this.id;
							var obj = getTopLeft(aftertip);
							var y = obj.top;
							var x = getElementWidth(aftertip) + obj.left;
							$("<div class='formValidateTip'></div>").appendTo(
									$("body")).css({
								left : x + "px",
								top : y + "px"
							}).prepend(
									$('<div id="' + tip + '"></div>').css(
											setting_temp.tipcss));
						}
						if (initConfig.tidymode) {
							jqobj.showTooltips()
						}
						;
					}

					// 每个控件都要保存这个配置信息
					setting.tipid = tip;
					$.formValidator.appendValid(this.id, setting);

					// 保存控件ID
					var validobjectids = initConfig.validobjectids;
					if (validobjectids.indexOf("#" + this.id + " ") == -1) {
						initConfig.validobjectids = (validobjectids == "" ? "#"
								+ this.id : validobjectids + ",#" + this.id);
					}

					// 初始化显示信息
					if (!initConfig.alertmessage) {
						$.formValidator.setTipState(this, "onShow",
								setting.onshow);
					}

					var srcTag = this.tagName.toLowerCase();
					var stype = this.type;
					var defaultval = setting.defaultvalue;
					// 处理默认值
					if (defaultval) {
						jqobj.val(defaultval);
					}

					if (srcTag == "input" || srcTag == "textarea") {
						// 注册获得焦点的事件。改变提示对象的文字和样式，保存原值
						jqobj.focus(function() {
							if (!initConfig.alertmessage) {
								// 保存原来的状态
								var tipjq = $("#" + tip);
								this.lastshowclass = tipjq.attr("class");
								this.lastshowmsg = tipjq.html();
								$.formValidator.setTipState(this, "onFocus",
										setting.onfocus);
							}
							if (stype == "password" || stype == "text"
									|| stype == "textarea" || stype == "file") {
								this.validoldvalue = jqobj.val();
							}
						});
						// 注册失去焦点的事件。进行校验，改变提示对象的文字和样式；出错就提示处理
						jqobj
								.bind(
										setting.triggerevent,
										function() {
											var settings = this.settings;
											var returnObj = $.formValidator
													.oneIsValid(this.id, 1);
											if (returnObj == null) {
												return;
											}
											if (returnObj.ajax >= 0) {
												$.formValidator
														.showAjaxMessage(returnObj);
											} else {
												var showmsg = $.formValidator
														.showMessage(returnObj);
												if (!returnObj.isvalid) {
													// 自动修正错误
													var auto = setting.automodify
															&& (this.type == "text"
																	|| this.type == "textarea" || this.type == "file");
													if (auto
															&& !initConfig.alertmessage) {
														alert(showmsg);
														$.formValidator
																.setTipState(
																		this,
																		"onShow",
																		setting.onshow);
													} else {
														if (initConfig.forcevalid
																|| setting.forcevalid) {
															alert(showmsg);
															this.focus();
														}
													}
												}
											}
										});
					} else if (srcTag == "select") {
						// 获得焦点
						jqobj.bind("focus", function() {
							if (!initConfig.alertmessage) {
								$.formValidator.setTipState(this, "onFocus",
										setting.onfocus);
							}
						});
						// 失去焦点
						jqobj.bind("blur", function() {
							jqobj.trigger("change")
						});
						// 选择项目后触发
						jqobj.bind("change", function() {
							var returnObj = $.formValidator.oneIsValid(this.id,
									1);
							if (returnObj == null) {
								return;
							}
							if (returnObj.ajax >= 0) {
								$.formValidator.showAjaxMessage(returnObj);
							} else {
								$.formValidator.showMessage(returnObj);
							}
						});
					}
				});
	};

	$.fn.inputValidator = function(controlOptions) {
		var settings = {
			isvalid : false,
			min : 0,
			max : 99999999999999,
			type : "size",
			onerror : "输入错误",
			validatetype : "InputValidator",
			empty : {
				leftempty : true,
				rightempty : true,
				leftemptyerror : null,
				rightemptyerror : null
			},
			wideword : true
		};
		controlOptions = controlOptions || {};
		$.extend(true, settings, controlOptions);
		return this.each(function() {
			$.formValidator.appendValid(this.id, settings);
		});
	};

	$.fn.compareValidator = function(controlOptions) {
		var settings = {
			isvalid : false,
			desid : "",
			operateor : "=",
			onerror : "输入错误",
			validatetype : "CompareValidator"
		};
		controlOptions = controlOptions || {};
		$.extend(true, settings, controlOptions);
		return this.each(function() {
			$.formValidator.appendValid(this.id, settings);
		});
	};

	$.fn.regexValidator = function(controlOptions) {
		var settings = {
			isvalid : false,
			regexp : "",
			param : "i",
			datatype : "enum",
			onerror : "输入格式不正确",
			validatetype : "RegexValidator"
		};
		controlOptions = controlOptions || {};
		$.extend(true, settings, controlOptions);
		return this.each(function() {
			$.formValidator.appendValid(this.id, settings);
		});
	};

	$.fn.functionValidator = function(controlOptions) {
		var settings = {
			isvalid : true,
			fun : function() {
				this.isvalid = true;
			},
			validatetype : "FunctionValidator",
			onerror : "输入错误"
		};
		controlOptions = controlOptions || {};
		$.extend(true, settings, controlOptions);
		return this.each(function() {
			$.formValidator.appendValid(this.id, settings);
		});
	};

	$.fn.ajaxValidator = function(controlOptions) {
		var settings = {
			isvalid : false,
			lastValid : "",
			type : "GET",
			url : "",
			addidvalue : true,
			datatype : "html",
			data : "",
			async : true,
			cache : false,
			beforesend : function() {
				return true;
			},
			success : function() {
				return true;
			},
			complete : function() {
			},
			processdata : false,
			error : function() {
			},
			buttons : null,
			onerror : "服务器校验没有通过",
			onwait : "正在等待服务器返回数据",
			validatetype : "AjaxValidator"
		};
		controlOptions = controlOptions || {};
		$.extend(true, settings, controlOptions);
		return this.each(function() {
			$.formValidator.appendValid(this.id, settings);
		});
	};

	$.fn.defaultPassed = function(onshow) {
		return this
				.each(function() {
					var settings = this.settings;
					for ( var i = 1; i < settings.length; i++) {
						settings[i].isvalid = true;
						if (!$.formValidator
								.getInitConfig(settings[0].validatorgroup).alertmessage) {
							var ls_style = onshow ? "onShow" : "onCorrect";
							$.formValidator.setTipState(this, ls_style,
									settings[0].oncorrect);
						}
					}
				});
	};

	$.fn.unFormValidator = function(unbind) {
		return this.each(function() {
			this.settings[0].bind = !unbind;
			if (unbind) {
				$("#" + this.settings[0].tipid).hide();
			} else {
				$("#" + this.settings[0].tipid).show();
			}
		});
	};

	$.fn.showTooltips = function() {
		if ($("body [id=fvtt]").length == 0) {
			fvtt = $("<div id='fvtt' style='position:absolute;z-index:56002'></div>");
			$("body").append(fvtt);
			fvtt
					.before("<iframe src='about:blank' class='fv_iframe' scrolling='no' frameborder='0'></iframe>");

		}
		return this
				.each(function() {
					jqobj = $(this);
					s = $("<span class='top' id=fv_content style='display:block'></span>");
					b = $("<b class='bottom' style='display:block' />");
					this.tooltip = $(
							"<span class='fv_tooltip' style='display:block'></span>")
							.append(s).append(b).css({
								"filter" : "alpha(opacity:95)",
								"KHTMLOpacity" : "0.95",
								"MozOpacity" : "0.95",
								"opacity" : "0.95"
							});
					// 注册事件
					jqobj.mouseover(function(e) {
						$("#fvtt").append(this.tooltip);
						$("#fv_content").html(this.Tooltip);
						$.formValidator.localTooltip(e);
					});
					jqobj.mouseout(function() {
						$("#fvtt").empty();
					});
					jqobj.mousemove(function(e) {
						$("#fv_content").html(this.Tooltip);
						$.formValidator.localTooltip(e);
					});
				});
	}

})(jQuery);

function getElementWidth(objectId) {
	x = document.getElementById(objectId);
	return x.offsetWidth;
}

function getTopLeft(objectId) {
	obj = new Object();
	o = document.getElementById(objectId);
	oLeft = o.offsetLeft;
	oTop = o.offsetTop;
	while (o.offsetParent != null) {
		oParent = o.offsetParent;
		oLeft += oParent.offsetLeft;
		oTop += oParent.offsetTop;
		o = oParent;
	}
	obj.top = oTop;
	obj.left = oLeft;
	return obj;
}